<!DOCTYPE html>
<html>
<head>
  <title></title>
  <style>
    body {
      color: white;
      font: 12px Consolas, "Liberation Mono", Courier, monospace;
    }

    canvas {
      background-color: #1a2633;
    }
  </style>
</head>
<body style="background-color: #333333;">
  <script src="../../build/ts/utilities.js"></script>
  <script src="../../build/ts/gfx/utilities.js"></script>
  <script src="../../build/ts/gfx/geometry.js"></script>
  <script src="../../build/ts/gfx/references.js"></script>
  <script src="../../build/ts/gfx/regionAllocator.js"></script>
  <table>
    <tr>
      <td>
        Compact Allocator
      </td>
      <td>
        Grid Allocator
      </td>
    </tr>
    <tr>
      <td>
        <canvas id="a" width="1024" height="512"></canvas>
      </td>
      <td>
        <canvas id="b" width="512" height="512"></canvas>
      </td>
    </tr>
    <tr>
      <td>
        <div id="aResults"></div>
      </td>
      <td>
        <div id="bResults"></div>
      </td>
    </tr>
  </table>


  <script>
    var Geometry = Shumway.GFX.Geometry;
    var RegionAllocator = Shumway.GFX.RegionAllocator;
    var SurfaceRegionAllocator = Shumway.GFX.SurfaceRegionAllocator;
    var a = document.getElementById("a").getContext("2d");
    var b = document.getElementById("b").getContext("2d");

    var aResults = document.getElementById("aResults");
    var bResults = document.getElementById("bResults");

    var W = 1024, H = 512;

  </script>
  <script>
    function testA() {
      var compact = new RegionAllocator.CompactAllocator(W, H);
      var grid = new RegionAllocator.GridAllocator(W, H, 64);

      var cRegions = [];
      var gRegions = [];

      setInterval(function () {
        var s = Date.now();
        for (var i = 0; i < 64; i++) {
          var w = (Math.random() * 16) | 0;
          var h = (Math.random() * 16) | 0;
          var c = compact.allocate(w, h);
          if (!c) {
            compact = new RegionAllocator.CompactAllocator(W, H);
            c = compact.allocate(w, h);
            cRegions.length = 0;
            a.clearRect(0, 0, a.canvas.width, a.canvas.height);
          }
          cRegions.push(c);
          a.fillStyle = Shumway.ColorStyle.randomStyle();
          a.fillRect(c.x, c.y, c.w, c.h);
        }
        aResults.innerHTML = "Total Regions: " + cRegions.length + " Amortized Allocation Time: " + (Date.now() - s) + " ms";

        var s = Date.now();
        for (var i = 0; i < 64; i++) {
          var w = (Math.random() * 16) | 0;
          var h = (Math.random() * 16) | 0;
          var g = grid.allocate(w, h);
          if (!g) {
            grid = new RegionAllocator.GridAllocator(W, H, 16);
            g = grid.allocate(w, h);
            gRegions.length = 0;
            b.clearRect(0, 0, b.canvas.width, b.canvas.height);
          }
          gRegions.push(g);
          b.fillStyle = Shumway.ColorStyle.randomStyle();
          b.fillRect(g.x, g.y, g.w, g.h);
        }
        bResults.innerHTML = "Total Regions: " + gRegions.length + " Amortized Allocation Time: " + (Date.now() - s) + " ms";
      }, 16);
    }

    function testB() {
      var compact = new RegionAllocator.CompactAllocator(W, H);
      var grid = new RegionAllocator.GridAllocator(W, H, 16);

      var cRegions = [];
      var gRegions = [];

      setInterval(function () {
        var s = Date.now();
        for (var i = 0; i < 64; i++) {
          var w = (Math.random() * 16) | 0;
          var h = (Math.random() * 16) | 0;
          var c = compact.allocate(w, h);
          if (!c) {
            var count = (cRegions.length / 2) | 0;
            for (var i = 0; i < count; i++) {
              compact.free(cRegions[i]);
            }
            cRegions = cRegions.slice(count);
            c = compact.allocate(w, h);
          }
          if (!c) {
            compact = new RegionAllocator.CompactAllocator(W, H);
            c = compact.allocate(w, h);
            a.clearRect(0, 0, a.canvas.width, a.canvas.height);
            cRegions.length = 0;
          }
          cRegions.push(c);
          a.fillStyle = Shumway.ColorStyle.randomStyle();
          a.fillRect(c.x, c.y, c.w, c.h);
        }
        aResults.innerHTML = "Total Regions: " + cRegions.length + " Amortized Allocation Time: " + (Date.now() - s) + " ms";

        var s = Date.now();
        for (var i = 0; i < 64; i++) {
          var w = (Math.random() * 16) | 0;
          var h = (Math.random() * 16) | 0;
          var g = grid.allocate(w, h);
          if (!g) {
            var count = (gRegions.length / 2) | 0;
            for (var i = 0; i < count; i++) {
              grid.free(gRegions[i]);
            }
            gRegions = gRegions.slice(count);
            g = grid.allocate(w, h);
          }
          gRegions.push(g);
          b.fillStyle = Shumway.ColorStyle.randomStyle();
          b.fillRect(g.x, g.y, g.w, g.h);
        }
        bResults.innerHTML = "Total Regions: " + gRegions.length + " Amortized Allocation Time: " + (Date.now() - s) + " ms";
      }, 16);
    }

    function testC() {
      var compact = new RegionAllocator.CompactAllocator(W, H);
      var grid = new RegionAllocator.GridAllocator(W, H, 16);

      var cRegions = [];
      var gRegions = [];

      setInterval(function () {
        var s = Date.now();
        for (var i = 0; i < 64; i++) {
          var size = (64 - i);
          var w = (Math.random() * size) | 0;
          var h = (Math.random() * size) | 0;
          var c = compact.allocate(w, h);
          if (!c) {
            var count = (cRegions.length / 2) | 0;
            for (var i = 0; i < count; i++) {
              compact.free(cRegions[i]);
            }
            cRegions = cRegions.slice(count);
            c = compact.allocate(w, h);
          }
          if (!c) {
            compact = new RegionAllocator.CompactAllocator(W, H);
            c = compact.allocate(w, h);
            a.clearRect(0, 0, a.canvas.width, a.canvas.height);
            cRegions.length = 0;
          }
          cRegions.push(c);
          a.fillStyle = Shumway.ColorStyle.randomStyle();
          a.fillRect(c.x, c.y, c.w, c.h);
        }
        aResults.innerHTML = "Total Regions: " + cRegions.length + " Amortized Allocation Time: " + (Date.now() - s) + " ms";
      }, 16);
    }

    function testD() {
      var bucketAllocator = new RegionAllocator.BucketAllocator(W, H);
      var bRegions = [];

      setInterval(function () {
        var s = Date.now();
        for (var i = 0; i < 64; i++) {
          var size = (64 - i);
          var w = (Math.random() * size) | 0;
          var h = (Math.random() * size) | 0;
          // debugger;
          // w = h = i;
          var c = bucketAllocator.allocate(w, h);
          if (!c) {
            bucketAllocator = new RegionAllocator.BucketAllocator(W, H);
            c = bucketAllocator.allocate(w, h);
            a.clearRect(0, 0, a.canvas.width, a.canvas.height);
            bRegions.length = 0;
          }
          bRegions.push(c);
          a.fillStyle = Shumway.ColorStyle.randomStyle();
          a.fillRect(c.x, c.y, c.w, c.h);
        }
        aResults.innerHTML = "Total Regions: " + bRegions.length + " Amortized Allocation Time: " + (Date.now() - s) + " ms";
      }, 16);
    }

    function testE() {
      var bucketAllocator = new RegionAllocator.BucketAllocator(W, H);

      var tick = 0;
      setInterval(function () {
        var t = Date.now();
        for (var i = 1; i < 32; i++) {
          var stack = [];
          for (var s = 0; s < 100; s++) {
            tick += 0.001;
            var size = (32 - i);
            var w = (Math.random() * size) | 0;
            var h = (Math.random() * size) | 0;
            w = h;
            w = h = i;
            w = h = 1 + ((Math.sin(tick) + 1) * 16) | 0;
            var c = bucketAllocator.allocate(w, h);
            if (!c) {
              break;
            } else {
              stack.push(c);
              a.fillStyle = Shumway.ColorStyle.randomStyle();
              a.fillRect(c.x, c.y, c.w, c.h);
            }
          }
          while (stack.length) {
            var r = stack.pop()
            bucketAllocator.free(r);
          }
        }
        aResults.innerHTML = "Amortized Stack Allocation Time: " + (Date.now() - t) + " ms";
      }, 16);
    }

  </script>
  <br>
  <button onclick="testA()">Allocate Until Full & Reset</button>
  <button onclick="testB()">Allocate Until Full & Remove Half Regions</button>
  <button onclick="testC()">Allocate Until Full & Remove Half Regions - Non Uniform</button>
  <button onclick="testD()">Bucket Allocate Until Full & Remove Half Regions - Non Uniform</button>
  <button onclick="testE()">Bucket Stack Allocate Non Uniform</button>
</body>
</html>